﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Net;
using System.IO;

namespace DiemDanh
{
    public partial class Attendance : Form
    {
        List<ComingEvent> eventsList = new List<ComingEvent>();//store uppcomming event items
        List<string> absentList = new List<String>();//store absent day info
        ArrayList result = new ArrayList();
        Form1 mainPanel;//Form1 object!
        string subName;//get current selected subject to view information
        string attendancePageSourceCode = null;
        bool isGetAbsentError = false;
        bool isGetComingEventError = false;

        public Attendance(Form1 mainForm,string subName)
        {
            InitializeComponent();
            this.mainPanel = mainForm;
            this.subName = subName;
            this.pictureBox1.Visible = true;
            string pageID = mainPanel.getPageID(subName);
            this.backgroundWorker1.RunWorkerAsync(pageID);  
        }

        /* @user: Nhan
         * @para: Default Event Para
         * @definition: Allow multi threading, check multiple subject and loading image, process on thread body
         */
        private void attFormLoading_DoWork(object sender, DoWorkEventArgs e)
        {
            string username = this.mainPanel.txtUsername.Text;
            string password = this.mainPanel.txtPassword.Text;
            string id = e.Argument.ToString();

            //do login and get cookies
            if (this.mainPanel.cookies == null) this.mainPanel.cookies = this.mainPanel.doLogin(username, password);
            //get information
            this.learningTracker(username, password, id, mainPanel.cookies);    
        }

       /* @user: Nhan
        * @para: Default Event Para
        * @definition: Allow multi threading, check multiple subject and loading image, process after thread done!
        */
        private void attFormLoading_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.pictureBox1.Visible = false;
            handleResult();
            this.getComingEvent();
            this.getAbsentDay();
            //this.lbLoading.Visible = false;
            //this.labelWelcome.Text = "Chào " + this.mainPanel.userFullName + " , bạn đang xem điểm danh môn " + this.subName; 
        }

       /* @user: Nhan
        * @para:none
        * @definition: Xử lý output kết quả, hiển thị ở form Attendance
        * @return: none
        */
        internal void handleResult()
        {
            if (this.result.Count > 0)
            {               
                string total = this.result[1].ToString();
                string completed = this.result[3].ToString();
                string present = this.result[5].ToString();
                string absent = this.result[7].ToString();
                string absentPercent = this.result[9].ToString();
                string grade = this.result[11].ToString();
                string daysleft = calAbsentDaysLeft(Int16.Parse(total), Int16.Parse(absent)).ToString();


                // Display result
                DateTime now = DateTime.Now;
                //welcome
                this.labelWelcome.Visible = true;
                this.labelWelcome.Text += " " + this.mainPanel.userFullName + ", bạn đang xem thông tin của môn " + this.subName;
                //current day
                this.labelToday.Text += " " + now.ToShortDateString();
                //total
                this.labelTotal.Text += " " + total;
                //over day
                this.labelPast.Text += " " + completed;
                //absent
                this.labelAbsent.Text += " " + absent;
                //percent
                this.labelPercent.Text += " " + absentPercent;
                //can stay home!
                this.labelAllow.Text += " " + daysleft;
            }
            else this.labelWelcome.Text = "ERROR!";
        }
       /* @user: Nhan
        * @para:none
        * @definition: Xử lý output kết quả, hiển thị ở form Attendance khi không lấy dc result
        * @return: none
        */
        internal void handleError()
        {
                // Display result
                DateTime now = DateTime.Now;
                //welcome
                this.labelWelcome.Visible = true;
                this.labelWelcome.Text += " #";
                //current day
                this.labelToday.Text += " #";
                //total
                this.labelTotal.Text += " #";
                //over day
                this.labelPast.Text += " #";
                //absent
                this.labelAbsent.Text += " #";
                //percent
                this.labelPercent.Text += " #";
                //can stay home!
                this.labelAllow.Text += " #";
        }


       /* @user: Nhan
        * @para: none
        * @definition: Hiển thông tin về các sự kiện sắp diễn ra lên gridview
        */
        internal void getComingEvent()
        {
            for (int i = 0; i < eventsList.Count; i++)
            {
                string[] e = { eventsList[i].name, eventsList[i].deadline };
                this.dgvEvent.Rows.Add(e);
            }
            if (this.eventsList.Count == 0)
            {
                this.dgvEvent.Rows.Add("Không có Sự Kiện nào");
            }
        }

       /* @user: Nhan
        * @para: none
        * @definition: Hiển thông tin các ngày user absent lên gridview
        */
        internal void getAbsentDay()
        {
            foreach (string absentDay in absentList)
            {
                string ad = absentDay.Replace("\r\n\t", " ").Replace("\r", "").Replace("\n", " ").Replace("\t", " ");
                this.dgvAbsentDay.Rows.Add(ad);
            }
            if (absentList.Count == 0)
            {
                this.dgvAbsentDay.Rows.Add("Chúc mừng bạn, bạn chưa nghỉ ngày nào!");
            }
        }

        /* @user: Quan
         * @para: 
         * @definition: calculate absent days left -> return Absent Day Left
         *              update: báo đã hết ngày nghỉ
         */
        private string calAbsentDaysLeft(int total, int absent)
        {
            //testing =.=
            int allow = total / 5; //số ngày được nghỉ -> 20%
            if (absent > allow)
                return "0 \n\n /!\\ Số ngày nghỉ đã vượt quá giới hạn cho phép"
                            +"\n\n - Bạn cần liên hệ ngay phòng ICT \nđể kiểm tra lại điểm danh"
                            +"\n -Hoặc phòng CTSV để đóng tiền học lại !";
            
            return (allow - absent).ToString();
        }

        /* @user: Nhan
         * @para: [string]url: certain url page which logined,[CookieContainer] cookies: cookies store login info 
         * @definition: Get source code of certain url which 
         */
        internal string getSourceCode(string url, CookieContainer cookies)
        {
            string responseData;
            HttpWebRequest webRequest = WebRequest.Create(url) as HttpWebRequest;
            webRequest.CookieContainer = cookies;
            StreamReader responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream());
            responseData = responseReader.ReadToEnd();
            responseReader.Close();
            return responseData;
        }

        /* @user: Nhan
         * @para: [string]responseData
         * @definition: get attendance page link after login and choose course
         * @return: attendance page link
         */
        internal string getAttendancePageLink(string responseData)
        {
            string attHref = null;
            try
            {
                var doc = new HtmlAgilityPack.HtmlDocument();
                doc.LoadHtml(responseData);
                //get attendance page link
                var attAnchor = doc.DocumentNode.SelectNodes("//li[@class='activity attforblock']").Descendants("a");
                foreach (var anchor in attAnchor)
                {
                    attHref = anchor.Attributes["href"].Value.ToString();
                }
            }
            catch (Exception ex)
            {
                string e = ex.ToString();
                return null;
            }
            return attHref;
        }

        /* @user: Nhan
         * @para: [string]attendancePageLink: link of attendance page, [cookieContainer]cookies : cookies which store logined info
         * @definition: get all attendance info of student
         * @return: none (store to the global variable itself)
         */
        internal void getAttendanceInfo(string attendancePageLink, CookieContainer cookies)
        {
            if (this.attendancePageSourceCode == null) this.attendancePageSourceCode = this.getSourceCode(attendancePageLink, cookies);
            string responseData = this.attendancePageSourceCode;
            try
            {
                var doc = new HtmlAgilityPack.HtmlDocument();
                doc.LoadHtml(responseData);
                //get attendance info
                var table = doc.DocumentNode.SelectSingleNode("//table[@class='list']"); //chọn bảng class = "list" attforblock
                var tds = table.Descendants("td"); //lọc hết các td của bảng đó
                var userNames = doc.DocumentNode.SelectSingleNode("//font[@size='+1']");

                //get user full name
                this.mainPanel.userFullName = userNames.InnerText;

                foreach (var td in tds)
                {
                    int i = 0;
                    if (i < 12)
                    {
                        this.result.Add(td.InnerText); //lấy phần text thôi! fixx
                    }
                }
            }
            catch (Exception e)
            {
                string ex = e.Message;
                MessageBox.Show("ERROR at getAttendanceInfo(); ");
                return;
            }
        }

        /* @user: Nhan
         * @para: [string] responseData: source code after choose course to view
         * @definition: get coming event
         * @return: none (store to the global variable itself)
         */
        internal void getComingEventInfo(string responseData)
        { 
            var doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(responseData);
            try
            {
                var events = doc.DocumentNode.SelectNodes("//div[@class='event']");
                if (events != null)
                {
                    ArrayList eventName = new ArrayList();
                    ArrayList eventDeadline = new ArrayList();
                    foreach (var ev in events)
                    {
                        int i = 0;

                        foreach (var e in ev.Descendants("a"))
                        {
                            if (i % 2 == 0)
                            {
                                eventName.Add(e.InnerText).ToString();
                            }
                            else
                            {
                                eventDeadline.Add(e.InnerText).ToString();
                            }
                            i++;
                        }
                    }

                    for (int i = 0; i < eventName.Count; i++)
                    {
                        if (!eventName[i].Equals("") && !eventDeadline[i].Equals(""))
                        {
                            this.eventsList.Add(new ComingEvent(eventName[i].ToString(), eventDeadline[i].ToString()));
                        }
                    }
                }
            }
            catch (Exception e)
            {
                string ex = e.Message;
                return;
            }
        }
        /* @user: Nhan
         * @para: [string]attendancePageLink: link of attendance page, [cookieContainer]cookies : cookies which store logined info
         * @definition: get absent day
         * @return: none (store to the global variable itself)
         */
        internal void getAbsentDayInfo(string attendancePageLink, CookieContainer cookies)
        {
            if (this.attendancePageSourceCode == null) this.attendancePageSourceCode = this.getSourceCode(attendancePageLink, cookies);
            string responseData = this.attendancePageSourceCode;

            if (responseData.IndexOf("No attendance records exist") != -1)
            {
                MessageBox.Show("BẠN CHỌN MÔN ĐÃ HỌC QUA RỒI\nTHÔNG TIN CỦA MÔN NÀY ĐÃ BỊ RESET\nBẠN VUI LÒNG CHỌN MÔN MÌNH ĐANG HỌC");
                this.isGetAbsentError = true;
                return;
            }

            if (!this.isGetAbsentError)
            {
                try
                {
                    var doc = new HtmlAgilityPack.HtmlDocument();
                    doc.LoadHtml(responseData);

                    //get absent information
                    var attendanceByDay = doc.DocumentNode.SelectSingleNode("//table[@class='submissions']").Descendants("tr");

                    foreach (var tr in attendanceByDay)
                    {
                        if (tr.InnerText.IndexOf("Absent") != -1)
                        {
                            this.absentList.Add(tr.InnerText);
                        }
                    }
                }
                catch (Exception ex)
                {
                    string e = ex.ToString();
                    return;
                }
            }
        }

        /* @user: Nhan
         * @para:[string] username, [string] password, [string] pageID, CookieContainer cookies
         * @definition: Learning tracker, keeptrack attendance, upcoming event, day absent.
         * @return: none
         */
        //mục đích chính là trả về array list kết quả cần tìm, lấy từ Website chứa các thông tin trong bảng attendance (table class = "list" )
        internal void learningTracker(string username, string password, string pageID, CookieContainer cookies)
        {
            CookieContainer cookied = this.mainPanel.cookies;
            string subjectPageURL = "http://cms-hcm.fpt.edu.vn/elearning/course/view.php?id=" + pageID;
            string responseData = this.getSourceCode(subjectPageURL, cookied);
            if (responseData.IndexOf("Enrolment key") != -1)
            {
                MessageBox.Show("!!!BE CAREFUL!!!\nBẠN ĐÃ CHỌN MÔN CHƯA HỌC\nNHẤN OK ĐỂ TIẾP TỤC!");
                return;
            }
            else
            {
                string attPageLink = this.getAttendancePageLink(responseData);
                this.getAttendanceInfo(attPageLink, cookied);
                //get coming event
                getComingEventInfo(responseData);
                //get absentDays
                getAbsentDayInfo(attPageLink, cookied);

                
            }
        }//end tracker();

    }//end class
}//end namespace
